package com.apes.framework.plugin.event;

import com.apes.framework.api.SpringManager;
import com.apes.oap.event.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 功能：事件监听器注入
 *
 * @author xul
 * @create 2017-12-06 14:30
 */
public class InitEventListener implements RopEventListener<AfterStartedRopEvent> {
    protected final Logger logger = LogManager.getLogger(InitEventListener.class);

    @Override
    public void onRopEvent(AfterStartedRopEvent ropEvent) {
        ApplicationContext context = ropEvent.getRopContext().getApplicationContext();
        if (SpringManager.getApplicationContext() == null) {
            SpringManager.setApplicationContext(context);
        }
        onRopEvent(ropEvent, context); /* 响应事件：AfterStartedRopEvent */
        registerListener(ropEvent, context); /* 注册其它事件（除AfterStartedRopEvent事件之外） */
    }

    /**
     * 响应事件：AfterStartedOapEvent
     **/
    private void onRopEvent(AfterStartedRopEvent event, ApplicationContext context) {
        List<RopEventListener> listeners = getListeners(event, context);
        listeners.sort(Comparator.comparing(RopEventListener::getOrder));
        for (RopEventListener listener : listeners) {
            listener.onRopEvent(event);
        }
    }

    private List<RopEventListener> getListeners(AfterStartedRopEvent event, ApplicationContext context) {
        List<RopEventListener> listeners = context.getBeansOfType(RopEventListener.class).values().stream()
                .filter(listener -> supportsEvent(listener, event.getClass())).collect(Collectors.toList());
        if (context.getParent() != null) {
            listeners.addAll(getListeners(event, context.getParent()));
        }
        return listeners;
    }

    private boolean supportsEvent(RopEventListener listener, Class<? extends OapEvent> eventType) {
        SmartRopEventListener smartListener = (listener instanceof SmartRopEventListener ? (SmartRopEventListener) listener : new GenericRopEventAdapter(listener));
        return (smartListener.supportsEventType(eventType));
    }

    /**
     * 注册其它事件（除AfterStartedRopEvent事件之外）
     */
    private void registerListener(AfterStartedRopEvent event, ApplicationContext context) {
        List<RopEventListener> listeners = context.getBeansOfType(RopEventListener.class).values().stream()
                .filter(listener -> !supportsEvent(listener, event.getClass())).collect(Collectors.toList());
        listeners.forEach(listener -> event.getRopContext().getEventMulticaster().addRopListener(listener));
        if (context.getParent() != null) {
            registerListener(event, context.getParent());
        }
    }

    @Override
    public int getOrder() {
        return 0;
    }

}
